package study.rabbitmq.publish.config;

import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pojo.User;

import javax.annotation.PostConstruct;

@Component
public class RabbitSender implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {

    @Autowired
    RabbitTemplate rabbitTemplate;

    public void testPublishMsg() {
        rabbitTemplate.convertAndSend("DIRECT_EXCHANGE","privateChart","你好呀，我是私聊你的");
        rabbitTemplate.convertAndSend("TOPIC_EXCHANGE","subcribe.xiaoming","你好呀，我是你关注了我的xiaoming");
        rabbitTemplate.convertAndSend("TOPIC_EXCHANGE","subcribe.school.xiaoqiang","你好呀，我是你关注了的同班同学xiaoqiang");
        rabbitTemplate.convertAndSend("FANOUT_EXCHANGE",null,"我是广播事件");
    }

    public void testDelayMsg() {
        rabbitTemplate.convertAndSend("DEAD_EXCHANGE", "dead", "我设置了过期时间4秒", new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                MessageProperties messageProperties = message.getMessageProperties();
                messageProperties.setExpiration("4000");
                return message;
            }
        });
    }

    public void testLimitMsg() {
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setAge(20);
            user.setName("ltf");
            rabbitTemplate.convertAndSend("LIMIT_EXCHANGE","limit",user);
        }
    }

    /**
     * 如果想在生成对象时完成某些初始化操作，
     * 而偏偏这些初始化操作又依赖于依赖注入，
     * 那么久无法在构造函数中实现。
     * 为此，可以使用@PostConstruct注解一个方法来完成初始化
     * ,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。
     */
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }


    /**
     * 通过实现ConfirmCallBack接口，消息发送到交换器Exchange后触发回调
     * 需要开启配置
     * spring.rabbitmq.publisher-confirms=true
     * spring.rabbitmq.publisher-returns=true
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        System.out.println("correlationData:"+correlationData+" ack:"+ack+" cause"+cause);
        if (ack) {
            System.out.println("成功发送到交换机");
        } else {
            System.out.println("发送失败，修改状态为失败 cause:"+cause);
        }
    }

    /**
     * 通过实现ReturnCallback接口，如果消息从交换器发送到对应队列失败时触发（比如根据发送消息时指定的routingKey找不到队列时会触发）
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("message:"+message+" replayCode:"+replyCode+" replayText:"+replyText+" exchange:"+exchange+" routingkey:"+routingKey);
    }
}
